<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: #000;
            display: flex;
            justify-content: center;
        }
        canvas {
            image-rendering: pixelated;
        }
    </style>
</head>
<body>
<canvas id="game"></canvas>
<script>
    const canvas = document.getElementById('game');
    const ctx = canvas.getContext('2d');

    // 屏幕适应
    function resize() {
        canvas.height = window.innerHeight;
        canvas.width = Math.min(window.innerHeight * 0.6, 500);
    }
    window.addEventListener('resize', resize);
    resize();

    // 游戏常量
    const BLOCK_SIZE = canvas.width / 16;
    const COLS = 10;
    const ROWS = 20;
    const COLORS = [
        '#00f0f0', '#f0a000', '#0000f0',
        '#f0f000', '#a000f0', '#f00000',
        '#00f000'
    ];

    // 游戏状态
    let score = 0, level = 1, lines = 0;
    let board = Array(ROWS).fill().map(() => Array(COLS).fill(0));
    let currentPiece, nextPiece;
    let lastTime = 0, dropInterval = 1000;
    let particles = [];
    let paused = false;
    let shake = 0;

    // 七种方块形状
    const SHAPES = [
        [[1,1,1,1]],                         // I
        [[1,1,1],[0,1,0]],                   // T
        [[1,1,1],[1,0,0]],                   // L
        [[1,1,1],[0,0,1]],                   // J
        [[1,1],[1,1]],                       // O
        [[1,1,0],[0,1,1]],                   // S
        [[0,1,1],[1,1,0]]                    // Z
    ];

    class Piece {
        constructor(shapeIndex) {
            this.shape = SHAPES[shapeIndex];
            this.color = COLORS[shapeIndex];
            this.x = COLS/2 - this.shape[0].length/2 |0;
            this.y = 0;
        }

        rotate() {
            let newShape = this.shape[0].map((_,i) =>
                this.shape.map(row => row[i]).reverse()
            );
            if (!this.collision(0, 0, newShape)) {
                this.shape = newShape;
            }
        }

        collision(xOffset, yOffset, shape = this.shape) {
            return shape.some((row, dy) =>
                row.some((cell, dx) => {
                    let nx = this.x + dx + xOffset;
                    let ny = this.y + dy + yOffset;
                    return cell && (nx < 0 || nx >= COLS || ny >= ROWS ||
                        (ny >= 0 && board[ny][nx]));
                })
            );
        }
    }

    // 粒子特效
    class Particle {
        constructor(x, y, color) {
            this.x = x;
            this.y = y;
            this.vx = (Math.random() - 0.5) * 15;
            this.vy = Math.random() * -20 - 10;
            this.life = 1;
            this.color = color;
            this.size = Math.random() * 6 + 3;
            this.angle = Math.random() * Math.PI * 2;
        }

        update() {
            this.x += this.vx;
            this.y += this.vy;
            this.vy += 0.8;
            this.life -= 0.015;
            this.size *= 0.97;
            this.angle += this.vx * 0.1;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.angle);
            ctx.globalAlpha = this.life;
            ctx.fillStyle = this.color;
            ctx.fillRect(-this.size/2, -this.size/2, this.size, this.size);
            ctx.restore();
        }
    }

    // 颜色调整函数
    function adjustColor(color, amount) {
        let col = color.startsWith('#') ? color.slice(1) : color;
        let bigint = parseInt(col, 16);
        let r = (bigint >> 16) & 255;
        let g = (bigint >> 8) & 255;
        let b = bigint & 255;
        r = Math.max(0, Math.min(255, r + amount));
        g = Math.max(0, Math.min(255, g + amount));
        b = Math.max(0, Math.min(255, b + amount));
        return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
    }

    // 游戏功能
    function createParticles(lines) {
        const intensity = Math.min(5, lines.length);
        shake = intensity * 3;
        lines.forEach(y => {
            for(let x = 0; x < COLS; x++) {
                for(let i = 0; i < 5 + intensity*3; i++) {
                    particles.push(new Particle(
                        x * BLOCK_SIZE + BLOCK_SIZE/2,
                        y * BLOCK_SIZE + BLOCK_SIZE/2,
                        `hsl(${Math.random()*360}, 100%, 70%)`
                    ));
                }
            }
        });
    }

    function calculateScore(lines) {
        const points = [100, 300, 600, 1000];
        score += points[lines-1] * level;
        lines += lines;
        level = Math.min(10, 1 + Math.floor(lines / 10));
        dropInterval = 1000 - (level-1)*80;
    }

    function drawBlock(x, y, color) {
        // 巧克力排块效果
        const innerSize = BLOCK_SIZE * 0.6;
        const innerOffset = (BLOCK_SIZE - innerSize)/2;
        const highlight = adjustColor(color, 30);
        const shadow = adjustColor(color, -30);

        // 基底颜色
        ctx.fillStyle = adjustColor(color, -20);
        ctx.fillRect(x, y, BLOCK_SIZE, BLOCK_SIZE);

        // 突起小方块
        ctx.fillStyle = color;
        ctx.fillRect(x + innerOffset, y + innerOffset, innerSize, innerSize);

        // 高光效果
        ctx.strokeStyle = highlight;
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(x + innerOffset, y + innerOffset);
        ctx.lineTo(x + innerOffset + innerSize, y + innerOffset);
        ctx.lineTo(x + innerOffset + innerSize, y + innerOffset + innerSize);
        ctx.stroke();

        // 阴影效果
        ctx.strokeStyle = shadow;
        ctx.beginPath();
        ctx.moveTo(x + innerOffset + innerSize, y + innerOffset + innerSize);
        ctx.lineTo(x + innerOffset, y + innerOffset + innerSize);
        ctx.lineTo(x + innerOffset, y + innerOffset);
        ctx.stroke();
    }

    function draw() {
        ctx.fillStyle = '#000';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // 屏幕震动效果
        ctx.save();
        if (shake > 0) {
            ctx.translate(
                (Math.random() - 0.5) * shake,
                (Math.random() - 0.5) * shake
            );
            shake *= 0.8;
        }

        // 游戏区域参数
        const gameWidth = COLS * BLOCK_SIZE;
        const gameX = (canvas.width - gameWidth)/2 - BLOCK_SIZE*2;

        // 绘制游戏区域边框
        ctx.save();
        ctx.translate(gameX, BLOCK_SIZE);
        ctx.strokeStyle = '#fff';
        ctx.lineWidth = 3;
        ctx.strokeRect(-3, -3, gameWidth + 6, ROWS*BLOCK_SIZE + 6);

        // 绘制当前方块
        currentPiece.shape.forEach((row, y) =>
            row.forEach((cell, x) => {
                if (cell) drawBlock(
                    (currentPiece.x + x) * BLOCK_SIZE,
                    (currentPiece.y + y) * BLOCK_SIZE,
                    currentPiece.color
                );
            })
        );

        // 绘制棋盘
        board.forEach((row, y) =>
            row.forEach((cell, x) => {
                if (cell) drawBlock(x*BLOCK_SIZE, y*BLOCK_SIZE, cell);
            })
        );

        // 绘制粒子
        particles.forEach(p => {
            p.update();
            p.draw();
        });
        particles = particles.filter(p => p.life > 0);
        ctx.restore();

        // 绘制信息
        ctx.fillStyle = '#fff';
        ctx.font = '18px Arial';
        // 左侧信息
        const infoX = gameX - BLOCK_SIZE*2;
        ctx.fillText(`Score: ${score}`, infoX, 30);
        ctx.fillText(`Level: ${level}`, infoX, 60);

        // 绘制下一个方块（缩小版）
        const nextSize = BLOCK_SIZE * 0.6;
        ctx.fillText('Next:', canvas.width - 100, 30);
        ctx.save();
        ctx.translate(canvas.width - 100, 60);
        ctx.scale(0.6, 0.6);
        nextPiece.shape.forEach((row, y) =>
            row.forEach((cell, x) => {
                if (cell) drawBlock(x * BLOCK_SIZE, y * BLOCK_SIZE, nextPiece.color);
            })
        );
        ctx.restore();

        ctx.restore(); // 结束屏幕震动
    }

    function update(time = 0) {
        if (paused) return requestAnimationFrame(update);

        const delta = time - lastTime;
        if (delta > dropInterval) {
            lastTime = time;
            if (!currentPiece.collision(0, 1)) {
                currentPiece.y++;
            } else {
                placePiece();
            }
        }

        draw();
        requestAnimationFrame(update);
    }

    function placePiece() {
        currentPiece.shape.forEach((row, y) =>
            row.forEach((cell, x) => {
                if (cell) {
                    board[currentPiece.y + y][currentPiece.x + x] = currentPiece.color;
                }
            })
        );

        // 消除行（修复沉降问题）
        const lines = [];
        board.forEach((row, y) => {
            if (row.every(cell => cell)) lines.push(y);
        });

        if (lines.length) {
            // 按降序消除行
            lines.sort((a, b) => b - a).forEach(y => board.splice(y, 1));
            Array(lines.length).fill().forEach(() => board.unshift(Array(COLS).fill(0)));
            createParticles(lines);
            calculateScore(lines.length);
        }

        currentPiece = nextPiece;
        nextPiece = new Piece(Math.random()*7 |0);
        if (currentPiece.collision(0, 0)) {
            alert('Game Over!');
            resetGame();
        }
    }

    function resetGame() {
        board = Array(ROWS).fill().map(() => Array(COLS).fill(0));
        score = 0; level = 1; lines = 0;
        currentPiece = new Piece(Math.random()*7 |0);
        nextPiece = new Piece(Math.random()*7 |0);
    }

    // 控制
    document.addEventListener('keydown', e => {
        if (e.key === 'Escape') paused = !paused;
        if (paused) return;

        switch(e.key) {
            case 'ArrowLeft': case 'a':
                if (!currentPiece.collision(-1, 0)) currentPiece.x--; break;
            case 'ArrowRight': case 'd':
                if (!currentPiece.collision(1, 0)) currentPiece.x++; break;
            case 'ArrowDown': case 's':
                if (!currentPiece.collision(0, 1)) currentPiece.y++; break;
            case 'ArrowUp': case 'w':
                currentPiece.rotate(); break;
            case ' ':
                while (!currentPiece.collision(0, 1)) currentPiece.y++;
                placePiece(); break;
        }
    });

    // 启动游戏
    resetGame();
    requestAnimationFrame(update);
</script>
</body>
</html>